package com.eastfair.projectcore.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eastfair.auth.dto.RoleDTO;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.entity.Role;
import com.eastfair.auth.vo.RoleVo;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.context.ContextConstants;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.exception.code.ExceptionCode;
import com.eastfair.projectcore.dto.InterfaceInfoDTO;
import com.eastfair.projectcore.entity.Dictionary;
import com.eastfair.projectcore.entity.InterfaceInfo;
import com.eastfair.projectcore.dto.InterfaceInfoSaveDTO;
import com.eastfair.projectcore.dto.InterfaceInfoUpdateDTO;
import com.eastfair.projectcore.dto.InterfaceInfoPageQuery;
import com.eastfair.projectcore.service.InterfaceInfoService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

import com.eastfair.boot.controller.SuperController;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eastfair.echo.core.EchoService;
import com.eastfair.core.base.R;
import com.eastfair.projectcore.vo.InterfaceInfoVO;
import com.eastfair.security.util.TenantUtil;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import com.netflix.loadbalancer.Server;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.eastfair.annotation.annotation.security.PreAuth;

import com.eastfair.boot.request.PageParams;
import com.eastfair.core.context.ContextUtil;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;


/**
 * <p>
 * 前端控制器
 * 接口信息
 * </p>
 *
 * @author ligang
 * @date 2023-05-10
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/interfaceInfo")
@Api(value = "InterfaceInfo", tags = "接口信息")
@PreAuth(replace = "projectcore:interfaceInfo:")
public class InterfaceInfoController extends SuperController<InterfaceInfoService, Long, InterfaceInfo, InterfaceInfoPageQuery, InterfaceInfoSaveDTO, InterfaceInfoUpdateDTO> {

    @Autowired
    private EchoService echoService;

    @Value("${desensitizer.enabled}")
    private Boolean desensitizerEnabled;

    @Autowired
    private WebApplicationContext applicationContext;

    @Value("${com.eastfair.systemScene}")
    private String projectSystemScene;


    @Value("${com.eastfair.projectId}")
    private Long commonProjectId;

    @Autowired
    TenantUtil tenantUtil;

    @Override
    public void handlerResult(IPage<InterfaceInfo> page) {
        // 想让返回值实现自动回显，请将此行代码打开
        // echoService.action(page);
    }

    /**
     * Excel导入后的操作
     *
     * @param list
     */
    @Override
    public R<Boolean> handlerImport(List<Map<String, String>> list) {
        List<InterfaceInfo> interfaceInfoList = list.stream().map((map) -> {
            InterfaceInfo interfaceInfo = InterfaceInfo.builder().build();
            //TODO 请在这里完成转换
            return interfaceInfo;
        }).collect(Collectors.toList());

        return R.success(baseService.saveBatch(interfaceInfoList));
    }


    /**
     * 处理参数
     *
     * @param params 分页参数
     */
    @Override
    public void handlerQueryParams(PageParams<InterfaceInfoPageQuery> params) {
        InterfaceInfoPageQuery pageQuery = params.getModel();

    }

    /**
     * 执行添加接口参数
     *
     * @param interfaceInfos 系统标识
     */
    @ApiOperation(value = "执行添加接口参数", notes = "执行添加接口参数")
    @PostMapping("/executeAllUrl")
    public R executeAllUrl(@RequestBody List<JSONObject> interfaceInfos) {
        List<InterfaceInfo> interfaceInfoList = JSONArray.parseArray(JSONObject.toJSONString(interfaceInfos), InterfaceInfo.class);
        if (CollectionUtil.isEmpty(interfaceInfoList)) {
            return R.success();
        }
        ContextUtil.setProjectId(commonProjectId);
        ContextUtil.setTenant(tenantUtil.getTenant());
        //查询没有的接口
        InterfaceInfoDTO interfaceInfoDTO = new InterfaceInfoDTO();
        interfaceInfoDTO.setIsEnabled(BusinessConstant.YES);
        interfaceInfoDTO.setSystemName(interfaceInfoList.get(0).getSystemName());
        List<InterfaceInfo> interfaceInfoList1 = baseService.list(interfaceInfoDTO, null);
        //并发
//        ExecutorService executorService = Executors.newCachedThreadPool();
//        executorService.submit(() -> {
        if (CollectionUtil.isNotEmpty(interfaceInfoList1)) {
//            List<String> fullUrlList = interfaceInfoList.stream().map(InterfaceInfo::getFullUrl).collect(Collectors.toList());
//            List<InterfaceInfo> removeInterfaceInfoList = interfaceInfoList1.stream().filter(s -> !fullUrlList.contains(s.getFullUrl())).collect(Collectors.toList());
//            //删除
//            if (CollectionUtil.isNotEmpty(removeInterfaceInfoList)) {
//                for (InterfaceInfo interfaceInfo : removeInterfaceInfoList) {
//                    interfaceInfo.setIsDeleted(BusinessConstant.NO);
//                    baseService.updateById(interfaceInfo);
//                }
//            }

            List<InterfaceInfo> saveInterfaceInfo = new ArrayList<>();
            List<InterfaceInfo> updInterfaceInfo = new ArrayList<>();
            for (InterfaceInfo interfaceInfo : interfaceInfoList) {
                interfaceInfo.setReplaceFullUrl(assmbleUrl(interfaceInfo.getFullUrl()));
                //1新增 2修改
                int type = 1;
                for (InterfaceInfo interfaceInfo1 : interfaceInfoList1) {
                    if (interfaceInfo.getFullUrl().equals(interfaceInfo1.getFullUrl())) {
                        interfaceInfo.setId(interfaceInfo1.getId());
                        type = 2;
                    }
                }
                if (type == 1) {
                    saveInterfaceInfo.add(interfaceInfo);
//                    baseService.save(interfaceInfo);
                } else if (type == 2) {
//                    baseService.updateById(interfaceInfo);
//                    updInterfaceInfo.add(interfaceInfo);
                }
            }
            if (CollectionUtil.isNotEmpty(saveInterfaceInfo)) {

                baseService.saveBatch(saveInterfaceInfo);
            }
            if (CollectionUtil.isNotEmpty(updInterfaceInfo)) {
                baseService.updateBatchById(updInterfaceInfo);
            }
        } else {
            baseService.saveBatch(interfaceInfoList);
        }
//        });
        return R.success();
    }

    //    @GetMapping("/getAllUrl")
    public List<JSONObject> getAllUrl() {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        List<JSONObject> list = new ArrayList<>();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("systemName", projectSystemScene);
            RequestMappingInfo info = m.getKey();
            HandlerMethod method = m.getValue();
            //获取当前方法所在类名
            Class<?> bean = method.getBeanType();
            //使用反射获取当前类注解内容
            Api api = bean.getAnnotation(Api.class);
            if (api != null) {
                try {
                    jsonObject.put("classExplain", api.tags()[0]);
                } catch (Exception e) {

                }
            }
            RequestMapping requestMapping = bean.getAnnotation(RequestMapping.class);
            String[] value = requestMapping.value();
            jsonObject.put("parent", value[0]);
            //获取方法上注解以及注解值
            ApiOperation methodAnnotation = method.getMethodAnnotation(ApiOperation.class);
            if (methodAnnotation != null) {
                String privilegeName = methodAnnotation.value();
                jsonObject.put("explain", privilegeName);
            }
            PatternsRequestCondition p = info.getPatternsCondition();
            for (String url : p.getPatterns()) {
                jsonObject.put("url", url);
            }
            jsonObject.put("className", method.getMethod().getDeclaringClass().getName());
            jsonObject.put("method", method.getMethod().getName());
            RequestMethodsRequestCondition methodsCondition = info.getMethodsCondition();
            for (RequestMethod requestMethod : methodsCondition.getMethods()) {
                jsonObject.put("methodType", requestMethod.toString());
            }
            jsonObject.put("fullUrl", jsonObject.getString("parent") + jsonObject.getString("url") + ":" + jsonObject.getString("methodType"));
            if (jsonObject.getString("className").indexOf("com.eastfair") > -1) {
                list.add(jsonObject);
            }
        }
        return list;
    }


    /**
     * 查询接口信息
     *
     * @param interfaceInfoDTO 系统标识
     */
    @ApiOperation(value = "分组查询接口信息", notes = "查询接口信息")
    @PostMapping("/queryInterfaceGroup")
    public R<Map<String, List<InterfaceInfo>>> queryInterfaceGroup(@RequestBody InterfaceInfoDTO interfaceInfoDTO) {
        if (StringUtils.isBlank(interfaceInfoDTO.getSystemName())) {
            return R.fail("请选择系统标识");
        }
        InterfaceInfoDTO queryInterfaceInfoDTO = new InterfaceInfoDTO();
        queryInterfaceInfoDTO.setSystemName(interfaceInfoDTO.getSystemName());
        List<InterfaceInfo> interfaceInfos = baseService.list(queryInterfaceInfoDTO, null);
        if (CollectionUtil.isNotEmpty(interfaceInfos)) {
            Map<String, List<InterfaceInfo>> group2 = interfaceInfos.stream().collect(Collectors.groupingBy(InterfaceInfo::getClassName));
            return R.success(group2);
//            List<InterfaceInfoVO> result = new ArrayList<>();
//            if (group2.values().size() == 1) {
//                return R.success(baseService.doToVos(interfaceInfos));
//            } else {
//                for (String parent : group2.keySet()) {
//                    if (CollectionUtil.isEmpty(result.stream().filter(s -> parent.equals(s.getParent())).collect(Collectors.toList()))) {
//                        for (InterfaceInfo interfaceInfo : interfaceInfos) {
//                            if (parent.equals(interfaceInfo.getParent())) {
//                                InterfaceInfoVO interfaceInfoVO = baseService.doToVo(interfaceInfo);
//                                interfaceInfoVO.setChildInterfaceInfoVOList(baseService.doToVos(group2.get(parent)));
//                                result.add(interfaceInfoVO);
//                            }
//                        }
//                    }
//
//                }
//            }
//            return R.success(result);
        }
        return R.success(null);
    }

    /**
     * 分组查询列名
     *
     * @param interfaceInfoDTO 系统标识
     */
    @ApiOperation(value = "分组查询列名", notes = "分组查询列名")
    @PostMapping("/queryTypeGroup")
    public R<List<String>> queryTypeGroup(@RequestBody InterfaceInfoDTO interfaceInfoDTO) {
        if (StringUtils.isBlank(interfaceInfoDTO.getSystemName())) {
            return R.fail("请选择系统标识");
        }

        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(InterfaceInfo::getSystemName, interfaceInfoDTO.getSystemName());
        queryWrapper.lambda().eq(InterfaceInfo::getIsDeleted, BusinessConstant.DELETE_NO);
        queryWrapper.groupBy("parent").select("parent");
        List<InterfaceInfo> interfaceInfoList = baseService.list(queryWrapper);
        if (CollectionUtil.isEmpty(interfaceInfoList)) {
            return R.success(null);
        }
        return R.success(interfaceInfoList.stream().map(InterfaceInfo::getParent).collect(Collectors.toList()));
    }


    /**
     * 分组查询系统名称
     */
    @ApiOperation(value = "分组查询系统名称", notes = "分组查询系统名称")
    @GetMapping("/querySystemGroup")
    public R<List<String>> querySystemGroup() {
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(InterfaceInfo::getIsDeleted, BusinessConstant.DELETE_NO);
        queryWrapper.groupBy("system_name").select("system_name");
        List<InterfaceInfo> interfaceInfoList = baseService.list(queryWrapper);
        if (CollectionUtil.isEmpty(interfaceInfoList)) {
            return R.success(null);
        }
        return R.success(interfaceInfoList.stream().map(InterfaceInfo::getParent).collect(Collectors.toList()));
    }


    /**
     * 查询系统
     */
    @ApiOperation(value = "查询系统", notes = "查询系统")
    @PostMapping("/querySystem")
    public R<List<InterfaceInfo>> querySystem(@RequestBody InterfaceInfoDTO interfaceInfoDTO) {
        List<InterfaceInfo> interfaceInfos = baseService.list(null, interfaceInfoDTO.getInterfaceIds());
        return R.success(interfaceInfos);
    }

    public String assmbleUrl(String url){
        StringBuilder stringBuilder = new StringBuilder();
        if(StringUtils.isNotBlank(url)){
            String[] urlStr = url.split("/");
            for(String s: urlStr){
                if(s.indexOf("{")>-1){
                    s="**";
                }
                stringBuilder.append(s);
                stringBuilder.append("/");
            }
            return stringBuilder.toString();
        }
        return url;
    }
}
